using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Scripting;
using UserScripts;

namespace Scripting
{
    public class ChatProcessor : IChatProcessor
    {
        // Used to filter swearwords
        Regex[] FilterPatterns;

        /// <summary>
        /// Constructor
        /// </summary>
        public ChatProcessor()
        {
            // Create some wordfilters
            FilterPatterns = new Regex[2];
            FilterPatterns[0] = new Regex("([f|F][u|U][c|C][k|K])");
            FilterPatterns[1] = new Regex("([s|S][h|H][i|I][t|T])");
        }

        /// <summary>
        /// Process chat text from a user.
        /// </summary>
        /// <param name="actor">Player handle.</param>
        /// <param name="message">Players message.</param>
        public void OnChatText(Actor actor, string message)
        {
            // Clean up message
            for (int i = 0; i < FilterPatterns.Length; ++i)
                message = FilterPatterns[i].Replace(message, "****");

            // Broadcast message
            RCScript.DispatchMessage(actor, "[" + actor.Name + "]: " + message, 0, 1);
        }

        /// <summary>
        /// Process a slash command from a user.
        /// </summary>
        /// <param name="actor">Player handle.</param>
        /// <param name="command">Uppercase commandname.</param>
        /// <param name="data">Command parameters</param>
        public void OnSlashCommand(Actor actor, string command, string data)
        {
            // Process commands

            
            // User is emoting
            if (command.Equals("me", StringComparison.CurrentCultureIgnoreCase))
            {
                RCScript.DispatchMessage(actor, "* " + actor.Name + " " + data, 0, 1);
            }

            // Send a message to everyone in the zone
            else if (command.Equals("yell", StringComparison.CurrentCultureIgnoreCase))
            {
                RCScript.DispatchMessage(actor, "<" + actor.Name + "> " + data, 0, 1000);
            }

            // Player is asking to trade or accepted a trade
            else if (command.Equals("trade", StringComparison.CurrentCultureIgnoreCase))
            {
                Trade(actor, command, data);
            }
            else if (command.Equals("accepttrade", StringComparison.CurrentCultureIgnoreCase))
            {
                AcceptTrade(actor, command, data);
            }
            else if (command.Equals("denytrade", StringComparison.CurrentCultureIgnoreCase))
            {
                DenyTrade(actor, command, data);
            }
            else if (command.Equals("testzone", StringComparison.CurrentCultureIgnoreCase))
            {
                TestZone(actor, command, data);
            }
            else if (command.Equals("twarp", StringComparison.CurrentCultureIgnoreCase))
            {
                actor.Warp(data, "Start");
            }
            else if (command.Equals("gmtest", StringComparison.CurrentCultureIgnoreCase))
            {
                if (actor.GM)
                    actor.Output("You are a GM!");
                else
                    actor.Output("You are not a GM!");
            }
            else if (command.Equals("gmswitch", StringComparison.CurrentCultureIgnoreCase))
            {
                //actor.GM = !actor.GM;
                //actor.Output("GM Switched");
                if (actor.GM == true)
                {
                    ChatGMRequest a = new ChatGMRequest();
                    a.SetPlayerAsGM(data);
                }
            }
            else if (command.Equals("item", StringComparison.CurrentCultureIgnoreCase))
            {
                List<string> Params = new List<string>(data.Split(' '));

                if (Params.Count == 1)
                {

                    actor.GiveItem(Params[0], 1);
                }
                else if (Params.Count == 2)
                {
                    int amount;
                    bool result = int.TryParse(Params[1], out amount);
                    if (result)
                    {
                        //for (int i = 0; i < amount; i++)
                        actor.GiveItem(Params[0], amount);
                    }
                    else
                    {
                        actor.Output("Invalid amount");
                    }

                }
                else if (Params.Count >= 3)
                {
                    int amount;
                    bool result = int.TryParse(Params[1], out amount);
                    if (result)
                    {
                        ChatItemGiveRequest IG = new ChatItemGiveRequest();
                        IG.GivePlayerItem(actor, Params[2], Params[1], amount);

                    }
                    else
                    {
                        actor.Output("Invalid amount");
                    }

                }
            }
            else if (command.Equals("who", StringComparison.CurrentCultureIgnoreCase))
            {

                LinkedList<Actor> ActorList = new LinkedList<Actor>();
                //ActorList = ZI.GetActors();
                actor.GetPosition();
                Scripting.Math.SectorVector SV = actor.GetPosition();
                ushort radius = 5;
                ZoneInstance ZI = new ZoneInstance();
                ZI = actor.Zone;
                ushort SectorMinX = (ushort)(SV.SectorX - radius);
                ushort SectorMinZ = (ushort)(SV.SectorZ - radius);
                ushort SectorMaxX = (ushort)(SV.SectorX + radius);
                ushort SectorMaxZ = (ushort)(SV.SectorZ + radius);

                if (SectorMinX != (int)(SV.SectorX - radius))
                    SectorMinX = 0;

                if (SectorMinZ != (int)(SV.SectorZ - radius))
                    SectorMinZ = 0;

                if (SectorMaxX != (int)(SV.SectorX + radius))
                    SectorMaxX = 65535;

                if (SectorMaxZ != (int)(SV.SectorZ + radius))
                    SectorMinX = 65535;

                ActorList = ZI.GetActors(ActorType.Player, SectorMinX, SectorMinZ, SectorMaxX, SectorMaxZ);
                actor.Output(0, "There are " + ActorList.Count + " players in " + actor.Zone.Name);
                foreach (Actor A in ActorList)
                {
                    actor.Output(0, A.Name);
                }
                
            }
            else if (command.Equals("loc", StringComparison.CurrentCultureIgnoreCase))
            {
                actor.Output(0, actor.GetPosition().ToString());
            }
            else if (command.Equals("whisper", StringComparison.CurrentCultureIgnoreCase))
            {
                List<string> Params = new List<string>(data.Split(' '));
                //actor.Output(0, 
                ChatWhisperRequest CW = new ChatWhisperRequest();
                CW.SendWhisper(actor, Params[0], data.Substring(data.IndexOf(' ')));
            }
            else if (command.Equals("guild", StringComparison.CurrentCultureIgnoreCase))
            {
                UserScripts.GuildWindow GW = actor.FindControl(UserScripts.GuildWindow.FormName) as UserScripts.GuildWindow;
                if (GW == null)
                {
                    UserScripts.GuildWindow guildForm;
                    guildForm = new UserScripts.GuildWindow(actor);
                    actor.CreateDialog(guildForm);
                }
                else
                {
                    GW.Visible = true; //Not closing my object correctly? Hack it!
                }
            }
            else if (command.Equals("bank", StringComparison.CurrentCultureIgnoreCase))
            {
                if (actor.FindControl(BankWindow.BankWindow_Name) == null)
                {
                    // Use this to just call the bank window for the actor
                    BankWindow bankForm = new BankWindow(actor);
                    actor.CreateDialog(bankForm);
                }
            }
            else
            {
                actor.Output("Unknown command: " + command);
                RCScript.Log("Unknown Command(" + command + ", " + actor.Name + ")");
            }

        }



        // Implementation of /trade
        private void Trade(Actor actor, string command, string data)
        {
            // If he has no trading global, make an empty one (as if trading was completed last time)
            if (!actor.Globals.ContainsKey("Trading"))
                actor.Globals["Trading"] = new byte[0];

            // Is the player OK to trade?
            if (actor.Globals["Trading"].Length == 0 || actor.Globals["Trading"][0] == 0)
            {
                // Launch trade script
                RCScript.Execute("Trading", "InviteTrade", new object[] { actor, data }, actor, null);
            }
        }



        // Implementation of /accepttrade
        private void AcceptTrade(Actor actor, string command, string data)
        {
            // If he has no trading global, make an empty one (as if trading was completed last time)
            if (!actor.Globals.ContainsKey("Trading"))
                actor.Globals["Trading"] = new byte[0];

            // Check if an accept is waiting
            if (actor.Globals["Trading"].Length > 0 && actor.Globals["Trading"][0] == 1)
            {
                // Launch trade script
                RCScript.Execute("Trading", "AcceptTrade", new object[] { actor, data }, actor, null);
            }
        }

        // Implementation of /denytrade
        private void DenyTrade(Actor actor, string command, string data)
        {
            // If he has no trading global, make an empty one (as if trading was completed last time)
            if (!actor.Globals.ContainsKey("Trading"))
                actor.Globals["Trading"] = new byte[0];

            // Check if an accept is waiting
            if (actor.Globals["Trading"].Length > 0 && actor.Globals["Trading"][0] == 1)
            {
                // Launch trade script
                RCScript.Execute("Trading", "DenyTrade", new object[] { actor, data }, actor, null);
            }
        }

        private void TestZone(Actor actor, string command, string data)
        {
            string LogMsg = string.Format("{0} is in {1}:{2}", new object[] { actor.Name, actor.Zone.Name, actor.Zone.InstanceIndex });

            actor.Output(LogMsg, System.Drawing.Color.Yellow);
            RCScript.Log(LogMsg);
        }
    }
}
